package org.bjf.config.ds;

import com.alibaba.druid.pool.DruidDataSource;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.MybatisConfiguration;
import com.baomidou.mybatisplus.core.config.GlobalConfig;
import com.baomidou.mybatisplus.core.config.GlobalConfig.DbConfig;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import com.baomidou.mybatisplus.core.handlers.MybatisEnumTypeHandler;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.session.SqlSessionFactory;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;

import javax.sql.DataSource;

@Configuration
@MapperScan(basePackages = {"org.bjf.modules.*.mapper",
        "org.bjf.modules.sys.mapper"}, sqlSessionFactoryRef = "userSessionFactory")
public class UserDataSourceConfig {

    static final String PACKAGE = "org.bjf.modules.user.mapper,org.bjf.modules.sys.mapper";
    private static final String MAPPERLOCATIONS = "classpath*:mapper/user/**/*.xml";
    private static final String TYPEALIASESPACKAGE = "org.bjf.modules.user.bean";

    @Bean(name = "userDataSource")
    @ConfigurationProperties(prefix = "spring.datasource")
    @Primary
    public DataSource dataSource() {
        return new DruidDataSource();
//        return DataSourceBuilder.create().build();
    }

    @Bean(name = "userTransactionManager")
    @Primary
    public DataSourceTransactionManager transactionManager(
            @Qualifier("userDataSource") DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }

    @Bean(name = "userSessionFactory")
    @Primary
    public SqlSessionFactory sessionFactory(
            @Qualifier("userDataSource") DataSource dataSource) throws Exception {

        //===1.mybatis-plus 配置
        DbConfig dbCfg = new DbConfig();
        //主键策略
        dbCfg.setIdType(IdType.AUTO);
        //逻辑删除
        dbCfg.setLogicDeleteValue("1");
        dbCfg.setLogicNotDeleteValue("0");
        GlobalConfig globalConfig = new GlobalConfig();
        globalConfig.setDbConfig(dbCfg);
        globalConfig.setMetaObjectHandler(new TimeMetaObjectHandler());

        // 字段的驼峰下划线转换
        MybatisConfiguration configuration = new MybatisConfiguration();
        configuration.setMapUnderscoreToCamelCase(Boolean.TRUE);
        //枚举支持
        configuration.setDefaultEnumTypeHandler(MybatisEnumTypeHandler.class);

        //===2.构造sessionFactory(mybatis-plus)
        final MybatisSqlSessionFactoryBean sf = new MybatisSqlSessionFactoryBean();
        sf.setDataSource(dataSource);
        sf.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(MAPPERLOCATIONS));
        sf.setTypeAliasesPackage(TYPEALIASESPACKAGE);
        sf.setGlobalConfig(globalConfig);
        sf.setConfiguration(configuration);
        // 分页插件
        MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();
        mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        sf.setPlugins(mybatisPlusInterceptor);

        return sf.getObject();
    }


    /**
     * 创建时间和更新时间设置为空，由数据库去维护
     */
    private static class TimeMetaObjectHandler implements MetaObjectHandler {
        @Override
        public void insertFill(MetaObject metaObject) {
            updateFill(metaObject);
        }

        @Override
        public void updateFill(MetaObject metaObject) {
            if (metaObject.hasSetter("ctime")) {
                metaObject.setValue("ctime", null);
            }
            if (metaObject.hasSetter("utime")) {
                metaObject.setValue("utime", null);
            }
        }
    }
}  